///
/// ArmyBodger 3
/// (c)2010 richyp
///
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Printing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ArmyBodger.Core;

namespace ArmyBodger.UI {
    /// <summary>
    /// Represents a printed list document that can be used in printpreviews
    /// </summary>
    public class ListPrintDocument : PrintDocument {
        /// <summary>
        /// The title font
        /// </summary>
        protected Font titleFont = new Font(FontFamily.GenericSansSerif, 16, FontStyle.Bold);
        /// <summary>
        /// The subtitle font
        /// </summary>
        protected Font subTitleFont = new Font(FontFamily.GenericSansSerif, 14, FontStyle.Bold);
        /// <summary>
        /// Font used for the Entry entries
        /// </summary>
        protected Font entryFont = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold);
        /// <summary>
        /// Normal font to use for everything else
        /// </summary>
        protected Font standardFont = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular);
        /// <summary>
        /// The Entry objects used
        /// </summary>
        protected EntryCollection entries = null;
        /// <summary>
        /// Current Entry index to render (spanning multiple pages)
        /// </summary>
        protected int currentEntryIndex = 0;
        /// <summary>
        /// Current page number
        /// </summary>
        protected int page = 0;
        /// <summary>
        /// Get/Set the Entries to print
        /// </summary>
        public EntryCollection Entries {
            get {
                return this.entries;
            }
            set {
                EntryCollection collection = value;
                List<string> categories = new List<string>();
                this.entries = value;
                foreach (Entry entry in collection) {
                    if (!categories.Contains(entry.Category)) {
                        categories.Add(entry.Category);
                    }
                }
                categories.Sort();
                this.entries = new EntryCollection();
                foreach (string category in categories) {
                    foreach (Entry entry in collection) {
                        if (entry.Category == category) {
                            this.entries.Add(entry);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// The ArmyBook this list is based on
        /// </summary>
        protected ArmyBook armyBook = null;
        /// <summary>
        /// Get/Set the ArmyBook used
        /// </summary>
        public ArmyBook ArmyBook {
            get {
                return this.armyBook;
            }
            set {
                this.armyBook = value;
            }
        }
        /// <summary>
        /// Call this method to start the rendering
        /// </summary>
        /// <param name="armyBook">The ArmyBook used</param>
        /// <param name="entries">The EntryCollection to print</param>
        public void PrintList(ArmyBook armyBook, EntryCollection entries) {
            this.armyBook = armyBook;
            this.entries = entries;
            this.currentEntryIndex = 0;
            this.Print();            
        }
        /// <summary>
        /// The overriden OnPrintPage method that is called by Print()
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPrintPage(PrintPageEventArgs e) {
            bool newPage = false;
            page++;
            List<string> categories = new List<string>();
            int top = e.MarginBounds.Top;
            int left = e.MarginBounds.Left;
            int right = e.MarginBounds.Right;
            int titleHeight = (int)e.Graphics.MeasureString("A", this.titleFont).Height;
            int subTitleHeight = (int)e.Graphics.MeasureString("A", this.subTitleFont).Height;
            int entryHeight = (int)e.Graphics.MeasureString("A", this.entryFont).Height;
            int standardHeight = (int)e.Graphics.MeasureString("A", this.standardFont).Height;
            int total = 0;
            int firstTop = 0;
            foreach (Entry entry in this.entries) {
                total += entry.Cost;
            }
            string title = this.armyBook.Header.GameSystem + " - " + this.armyBook.Header.Name;
            title += " Pg. " + page;
            e.Graphics.DrawString(title, this.titleFont, Brushes.Black, left, top);
            e.Graphics.DrawString(total + " pts", this.titleFont, Brushes.Black, right - 100, top);
            top += titleHeight;
            
            for (int index = currentEntryIndex; index < this.entries.Count; index++) {
                Entry current = this.entries[index];
                if (!categories.Contains(current.Category)) {
                    top += subTitleHeight;
                    categories.Add(current.Category);
                    e.Graphics.DrawString(
                        current.Category,
                        this.subTitleFont,
                        Brushes.Black,
                        left,
                        top
                        );                    
                    top += subTitleHeight;
                    e.Graphics.DrawLine(
                        Pens.Black, left, top, right, top
                        );
                    top += 5;
                }
                if (firstTop == 0) {
                    firstTop = top;
                }
                e.Graphics.DrawString(current.Name, this.entryFont, Brushes.Black, left, top);
                e.Graphics.DrawString(current.Cost.ToString() + "pts", this.entryFont, Brushes.Black, right - 50, top);
                top += entryHeight;
                e.Graphics.DrawString(current.Description, this.standardFont, Brushes.Black, left, top);
                top += standardHeight;
                e.Graphics.DrawLine(Pens.DarkGray, left, top, right, top);
                top += 5;
                if (top + entryHeight + standardHeight >= e.MarginBounds.Bottom) {
                    newPage = true;
                    top = e.MarginBounds.Top;
                    this.currentEntryIndex = index + 1;
                    break;
                }
            }

            e.Graphics.DrawLine(Pens.LightGray, right - 50, firstTop, right - 50, top );
            if (newPage) {
                e.HasMorePages = true;
            }
        }
    }
}
